package com.example.administrator.myapplication.net;

import com.example.administrator.myapplication.net.chain.CallServerInterceptor;
import com.example.administrator.myapplication.net.chain.ConnectionInterceptor;
import com.example.administrator.myapplication.net.chain.HeaderInterceptor;
import com.example.administrator.myapplication.net.chain.Interceptor;
import com.example.administrator.myapplication.net.chain.InterceptorChain;
import com.example.administrator.myapplication.net.chain.RetryInterceptor;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class Call {
    private Request request;
    private HttpClient httpClient;
    private boolean executed;
    private boolean canceled;

    public Call(Request request, HttpClient httpClient) {
        this.request = request;
        this.httpClient = httpClient;
    }

    public HttpClient client() {
        return httpClient;
    }

    public Request request() {
        return request;
    }

    public void enqueue(Callback callback) {
        synchronized (this) {
            if (executed) {
                throw new IllegalStateException("已经执行过");
            } else {
                executed = true;
            }
            httpClient.dispatcher().enqueue(new AsyncCall(callback));
        }
    }

    public boolean isCanceled() {
        return canceled;
    }

    public void cancel() {
        canceled = true;
    }


    class AsyncCall implements Runnable {
        private Callback callback;


        public AsyncCall(Callback callback) {
            this.callback = callback;
        }

        public String host() {
            return request.url().host;
        }


        @Override
        public void run() {

            //是否回调过
            boolean signalledCallback = false;
            try {
                Response response = getResponse();
                if (canceled) {
                    signalledCallback = true;
                    callback.onFailure(Call.this, new IOException("request was canceled"));
                    return;
                } else {
                    signalledCallback = true;
                    callback.onResponse(Call.this, response);
                }
            } catch (Exception e) {
                if (!signalledCallback) {
                    callback.onFailure(Call.this, e);
                }
            } finally {
                httpClient.dispatcher().finish(this);
            }

        }


    }

    private Response getResponse() throws Exception {
        List<Interceptor> interceptors = new ArrayList<>();
        interceptors.add(new RetryInterceptor());
        interceptors.add(new HeaderInterceptor());
        interceptors.add(new ConnectionInterceptor());
        interceptors.add(new CallServerInterceptor());
        InterceptorChain chain = new InterceptorChain(interceptors, 0, this);
        return chain.process();
    }
}
